package Task;

import java.io.IOException;
import java.nio.file.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class FileWatcher {
    private final Path watchPath;
    private final ExecutorService executor;
    private volatile boolean running = true;

    public FileWatcher(String folderPath) {
        this.watchPath = Paths.get(folderPath);
        this.executor = Executors.newSingleThreadExecutor();
    }

    public void startWatching() {
        if (!Files.exists(watchPath)) {
            System.err.println("监听路径不存在: " + watchPath);
            return;
        }

        System.out.println("开始监听文件夹: " + watchPath);

        executor.submit(() -> {
            try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
                // 注册监听器，监听创建事件
                watchPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

                // 递归注册子目录
                registerSubDirectories(watchPath, watchService);

                while (running) {
                    WatchKey key = watchService.take();

                    for (WatchEvent<?> event : key.pollEvents()) {
                        if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
                            Path newFile = (Path) event.context();
                            Path fullPath = ((Path) key.watchable()).resolve(newFile);
                            
                            System.out.println("检测到新条目: " + fullPath + " (目录: " + Files.isDirectory(fullPath) + ")");

                            // 如果是目录，注册监听
                            if (Files.isDirectory(fullPath)) {
                                registerDirectory(fullPath, watchService);
                            }
                            // 只处理.dat文件
                            else if (fullPath.toString().toLowerCase().endsWith(".dat")) {
                                System.out.println("检测到新文件: " + fullPath);
                                processNewFile(fullPath.toString());
                            } else {
                                System.out.println("忽略非.dat文件: " + fullPath);
                            }
                        }
                    }

                    if (!key.reset()) {
                        break;
                    }
                }
            } catch (IOException | InterruptedException e) {
                System.err.println("文件监听器异常: " + e.getMessage());
                e.printStackTrace();
            }
        });
    }

    private void registerSubDirectories(Path dir, WatchService watchService) throws IOException {
        // 递归注册所有子目录
        Files.walk(dir)
                .filter(Files::isDirectory)
                .forEach(subDir -> {
                    try {
                        registerDirectory(subDir, watchService);
                    } catch (IOException e) {
                        System.err.println("注册目录监听失败: " + subDir);
                        e.printStackTrace();
                    }
                });
    }

    private void registerDirectory(Path dir, WatchService watchService) throws IOException {
        try {
            dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
            System.out.println("注册目录监听: " + dir);
        } catch (IOException e) {
            System.err.println("注册目录监听失败: " + dir);
            throw e;
        }
    }

    private void processNewFile(String filePath) {
        try {
            System.out.println("开始处理新文件: " + filePath);

            // 等待文件写入完成（避免文件还在写入时就开始处理）
            Thread.sleep(2000);

            // 检查文件是否可读
            Path path = Paths.get(filePath);
            if (!Files.exists(path) || !Files.isReadable(path)) {
                System.out.println("文件不可读，跳过: " + filePath);
                return;
            }

            // 检查文件大小是否稳定（文件还在写入）
            long size1 = Files.size(path);
            Thread.sleep(1000);
            long size2 = Files.size(path);

            if (size1 != size2) {
                System.out.println("文件还在写入中，等待完成: " + filePath);
                return;
            }

            // 调用解析器处理文件
            FiberTestParserV4.processSingleFile(filePath);

        } catch (Exception e) {
            System.err.println("处理新文件失败: " + filePath);
            e.printStackTrace();
        }
    }

    public void stop() {
        running = false;
        executor.shutdown();
        try {
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
        }
        System.out.println("文件监听器已停止");
    }

    public static void main(String[] args) {
        // 监听data文件夹
        String watchFolder = "src/main/resources/data";

        System.out.println("启动文件监听器...");
        System.out.println("监听路径: " + watchFolder);
        System.out.println("按 Ctrl+C 停止程序");

        FileWatcher watcher = new FileWatcher(watchFolder);

        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("\n正在关闭文件监听器...");
            watcher.stop();
        }));

        watcher.startWatching();

        // 保持程序运行
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            System.out.println("程序被中断");
        }
    }
}